package com.vr.cloudpicture.manager;

import cn.hutool.core.util.StrUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * 多级缓存通用代码
 *
 * @author hzh
 * @date 2025/05/16
 */
@Service
public class CacheManager {
    private final StringRedisTemplate redisTemplate;
    private static final Cache<String,String> LOCAL_CACHE;
    static {
        // 初始化
        LOCAL_CACHE= Caffeine.newBuilder()
                .initialCapacity(1024)
                .maximumSize(10000L)
                // 在写后1分钟过期
                .expireAfterWrite(1L, TimeUnit.MINUTES)
                .build();
    }
    public CacheManager(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 获取或加载缓存
     *
     * @param cacheKey 缓存键
     * @param supplier 提供缓存数据
     * @return {@code String }
     */
    public String getOrLoad(String cacheKey, Supplier<String> supplier) {
        // 构建缓存key
        // 先从本地缓存获取
        String cacheValue = LOCAL_CACHE.getIfPresent(cacheKey);
        if(!StrUtil.isBlank(cacheValue)) {
            // 命中本地缓存
            return cacheValue;
        }
        // 本地缓存未命中时,查询分布式缓存Redis
        cacheValue = redisTemplate.opsForValue().get(cacheKey);
        if (!StrUtil.isBlank(cacheValue)) {
            // 命中分布式缓存Redis
            // 重建本地缓存
            LOCAL_CACHE.put(cacheKey, cacheValue);
            return cacheValue;
        }
        // 缓存都为命中时,调用 supplier 获取数据
        String result = supplier.get();
        // 重建缓存
        if (!StrUtil.isBlank(result)) {
            LOCAL_CACHE.put(cacheKey, result);
            redisTemplate.opsForValue().set(cacheKey, result, 1, TimeUnit.MINUTES);
        }
        return result;
    }
}
